package com.fintech.pangu.autoconfigure.security.oauth2.client;


import com.fintech.pangu.autoconfigure.security.PanGuWebSecurityConfigurationAdapter;
import com.fintech.pangu.autoconfigure.security.properties.PanGuSecurityProperties;
import com.fintech.pangu.security.authorize.AuthorizeConfigManager;
import com.fintech.pangu.security.config.PanGuAuthenticationManagerBuilderManager;
import com.fintech.pangu.security.config.PanGuHttpSecurityManager;
import com.fintech.pangu.security.oauth2.sso.client.endpoint.OAuth2UserDetailEndpoint;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.web.filter.ForwardedHeaderFilter;


/**
 * 单点登录客户端自动配置类
 */
//@EnableOAuth2Client  // 转移到@EnablePanGuOAuthSsoClient
@Import({ResourceServerTokenServicesConfiguration.class})
@Configuration
@EnableConfigurationProperties(PanGuSecurityProperties.class)  //只需启用PanGuSecurityProperties，已包含其它所有安全相关配置
@ConditionalOnClass(OAuth2Authentication.class)
@ConditionalOnBean(annotation = EnablePanGuOAuth2SsoClient.class)
@Order(101)
public class OAuth2SsoClientSecurityAutoConfiguration extends PanGuWebSecurityConfigurationAdapter {

    /**
     * PanGu安全相关的所有配置
     */
    @Autowired
    private PanGuSecurityProperties panGuSecurityProperties;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private AuthorizationCodeResourceDetails authorizationCodeResourceDetails;


    /**
     * 构造，将PanGuSecurityProperties传入父类
     * @param panGuSecurityProperties
     */
    public OAuth2SsoClientSecurityAutoConfiguration(
            PanGuSecurityProperties panGuSecurityProperties,
            PasswordEncoder passwordEncoder,
            ObjectProvider<PanGuHttpSecurityManager> panGuHttpSecurityManager,
            ObjectProvider<AuthorizeConfigManager> authorizeConfigManager,
            ObjectProvider<PanGuAuthenticationManagerBuilderManager> panGuAuthenticationManagerBuilderManager) {
        super(panGuSecurityProperties, passwordEncoder, panGuHttpSecurityManager.getIfAvailable(), authorizeConfigManager.getIfAvailable(), panGuAuthenticationManagerBuilderManager.getIfAvailable());
    }

    /**
     * 处理 单点登录成功后跳转、获取usrInfo的Controller
     * @return
     */
    @Bean
    public OAuth2UserDetailEndpoint oAuth2UserDetailEndpoint(){
        return new OAuth2UserDetailEndpoint();
    }



    /**
     * 自定义sso client场景下的HttpSecurity
     * @param http
     * @throws Exception
     */
    @Override
    protected void customHttpSecurity(HttpSecurity http) throws Exception {
        // OAuth2 Client SSO安全配置
        new OAuth2SsoSecurityConfigurer(
                applicationContext,
                panGuSecurityProperties)
            .configure(http);

        // OAuth2 Client SSO自动登出配置
        new OAuth2SsoClientAutoLogoutConfigurer(
                applicationContext,
                panGuSecurityProperties)
            .configure(http);

        // OAuth2 Client SSO Session策略配置
        new OAuth2SsoClientSessionStrategyConfigurer(
                panGuSecurityProperties)
            .configure(http);
    }

    /**
     * 处理请求头中X-Forwarded-x的Filter
     * @return
     */
    @Bean
    FilterRegistrationBean forwardedHeaderFilter() {
        FilterRegistrationBean filterRegBean = new FilterRegistrationBean();
        filterRegBean.setFilter(new ForwardedHeaderFilter());
        filterRegBean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return filterRegBean;
    }


    /**
     * OAuth2 Client关于授权码流程相关配置
     */
    //@Bean
    //@ConfigurationProperties("security.oauth2.client")
    //public AuthorizationCodeResourceDetails authorizationCodeResourceDetails() {
    //    AuthorizationCodeResourceDetails authorizationCodeResourceDetails = new AuthorizationCodeResourceDetails();
    //    authorizationCodeResourceDetails.setAccessTokenUri(panGuSecurityProperties.getOauth2().getSsoClient().getAuthServerUri() + "/oauth/token");
    //    authorizationCodeResourceDetails.setUserAuthorizationUri(panGuSecurityProperties.getOauth2().getSsoClient().getAuthServerUri() + "/oauth/authorize");
    //    authorizationCodeResourceDetails.setGrantType("authorization_code");
    //    return authorizationCodeResourceDetails;
    //}


    /**
     * 获取用户信息资源服务相关配置
     */
    //@Bean
    //@Primary
    //@ConfigurationProperties("security.oauth2.resource")
    //public ResourceServerProperties resourceServerProperties() {
    //    ResourceServerProperties resourceServerProperties = new ResourceServerProperties();
    //    //resourceServerProperties.setPreferTokenInfo(false); // 使用userInfo端点
    //    resourceServerProperties.setPreferTokenInfo(true); // 使用check_token端点
    //    //resourceServerProperties.setUserInfoUri(panGuSecurityProperties.getOauth2().getSsoClient().getAuthServerUri() + "/oauth/resource/userDetails");
    //    resourceServerProperties.setTokenInfoUri(panGuSecurityProperties.getOauth2().getSsoClient().getAuthServerUri() + "/oauth/check_token");
    //    return resourceServerProperties;
    //}

}
